%% 存储服务模块
%% 存储服务中存储了所有的name:value的数据
-module(xbt_storage_server).

-behaviour(gen_server).
%% gen_server回调函数
%% gen_server不提供直接的外部调用，全部通过gen_server的call、cast进行操作
-export([init/1,handle_call/3,handle_cast/2,
         handle_info/2,terminate/2,code_change/3]).
%% server启动
-export([start/0,start_link/0]).

-include("xbt.hrl").


start()           ->
    gen_server:start(?MODULE,[],[]).

%% 调用gen_server启动存储服务，这个调用是由supervisor调用的，不由用户直接调用
start_link()           ->
    gen_server:start_link({local,?MODULE},?MODULE,[],[]).

%% 初始化存储服务，gen_server的回调
%% 返回值
%% {ok,{ok,启用的存储模块}} 启用模块成功
%% {ok,none} 无法找到指定的存储模块
init([])    ->
    % 从配置文件中找出存储服务的实现模块，当前只有xbt_storage_dets一种实现
    Module = xbt_config:get_config(storage_mod),
    case Module of
        none          ->
            {ok,none};
        _             ->
            DataFile  = xbt_config:get_config(datafile),
            % 启用用户指定的存储模块
            apply(Module,start,[DataFile]),
            % 启用成功了之后把存储服务节点加入dht网络中
            xbt_dht:join(),
            {ok,{ok,Module}}
    end.

%% 存储服务中止
terminate(normal,{ok,Module}) ->
    % 将存储服务模块做退出操作
    apply(Module,stop,[]),
    % 将存储服务节点从dht网络中注销
    xbt_dht:leave();

terminate(normal,_Module) ->
    ok.

handle_cast(_Msg, State) ->
    {noreply,State}.

%% set(Name,Value)
handle_call({set,Name,Value},_From,{ok,Module}) ->
    case apply(Module,xbt_set,[Name,Value]) of
        ok            ->
            {reply,ok,{ok,Module}};
        {error,Error} ->
            {reply,Error,{ok,Module}}
    end;

%% append(Name,Value)
handle_call({append,Name,Value},_From,{ok,Module}) ->
    case apply(Module,xbt_append,[Name,Value]) of
        ok            ->
            {reply,ok,{ok,Module}};
        {error,Error} ->
            {reply,Error,{ok,Module}}
    end;

%% get(Name)
handle_call({get,Name},_From,{ok,Module}) ->
    Reply = apply(Module,xbt_get,[Name]),
    {reply,Reply,{ok,Module}};

%% delete(Name)
handle_call({delete,Name},_From,{ok,Module}) ->
    case apply(Module,xbt_delete,[Name]) of
        ok            ->
            {reply,ok,{ok,Module}};
        {error,Error} ->
            {reply,Error,{ok,Module}}
    end;

handle_call(_Msg,_From,State) ->
    {reply,error,State}.

handle_info(_Info, State) ->
    {noreply, State}.

code_change(_OldVsn, State, _Extra) ->
    {ok, State}.

